import os
import pickle
import random
from typing import Dict as D

import func_timeout
import trimesh
from OCC.Core.BRep import BRep_Builder
from OCC.Core.TopoDS import TopoDS_Compound
from OCC.Extend.DataExchange import write_step_file
# from group.jxq import group
# from new_json.jxq.path_generator import *
from OCC.Extend.DataExchange import write_stl_file
from fastapi import FastAPI
from func_timeout import func_set_timeout

from jxq.clamp_composition import ClampComposition
from jxq.data_porcessing import PointsJsonParser
from jxq.path_helper import *
from utils.occ_to_gltf import ShapeToGlb
from utils.oss import download_file_from_oss, upload_file_to_oss

app = FastAPI()
OSS_STL_PATH = "DO-Design_Dev/connectorsGlb"


def pickle2compound(pickle_path, local_pickle_path):
    if isinstance(pickle_path, str):
        if pickle_path.startswith('DO-Design_Dev'):
            download_file_from_oss(
                oss_file_name=pickle_path,
                local_file_name=local_pickle_path
                )

    p2 = open(local_pickle_path, 'rb')
    group_list = pickle.load(p2)
    p2.close()
    compound = TopoDS_Compound()
    B = BRep_Builder()
    B.MakeCompound(compound)
    for group in group_list:
        group.compound()
        B.Add(compound, group.compound())

    return compound


def point_change(points_pair, matrix):
    for i in range(len(points_pair)):
        for key, value in points_pair[i].items():
            if key == "rps_type" or key == "adjust_times":
                continue
            else:
                value = np.append(value, 0)
                temp = np.dot(matrix, value)
                new_value = np.delete(temp, -1)
                points_pair[i][key] = new_value
    return points_pair


# @app.post('/')
@app.post('/dodesign_ai/connector/generation')
async def clamp(json_file: D):
    try:
        out_json = clamp_generation(json_file)
        # return out_json
    # 若调用函数超时自动走异常(可在异常中写超时逻辑处理)
    except func_timeout.exceptions.FunctionTimedOut:
        out_json = {"code": 400,
                    "data": {},
                    "msg": "time out"}
    return out_json


@func_set_timeout(80)
def clamp_generation(json_file: D):
    if len(json_file['Rps']) > 0:
        point = json_file['Rps'][0]['Point']
    elif len(json_file['Rps']) == 0:
        point = None
    parser = PointsJsonParser(json_file)

    if json_file['pickle'].endswith(".stp"):
        compound = parser.load_stp()
    else:
        compound = parser.pickle2compound()

    if json_file["WorkPath"] == "":
        work_mesh = None
    else:
        work_mesh = parser.get_work_mesh()

    # work_mesh=None
    stl_file = os.path.join('./', 'temp02.stl')
    write_stl_file(compound, stl_file)

    points_pair = parser.get_points_pair()

    clamp = trimesh.load('temp02.stl')
    mesh = clamp + work_mesh
    res = 4

    # clamp.show()
    # v0=points_pair[0]["start_axis"].tolist()
    # v1=[1,0,0]
    # M = rotation_matrix(angle_between_vectors(v0, v1), vector_product(v0, v1))
    #
    # M_1 = inverse_matrix(M)
    # clamp.apply_transform(M)
    # work_mesh.apply_transform(M)

    # points_pair2 = point_change(points_pair,M)

    print("开始计算")
    t1 = time.perf_counter()
    CC = ClampComposition(points_pair, compound, clamp, work_mesh, res, point)

    t2 = time.perf_counter()

    print("计算完毕")
    print(t2 - t1)

    # CC.show_paths()
    try:
        connectors = CC.create_connecters()
        code = 200
        msg = "success"
        out_json = CC.to_json()
        out_json["Part"] = {"glb_path": [],
                            "stp_path": []}

        for connecter in connectors:
            random_num = random.randrange(0, 6553555)
            glb_name = str(random_num)
            ShapeToGlb(shape=connecter, path='./', filename=glb_name)
            write_step_file(connecter, filename=glb_name + ".stp")
            upload_file_to_oss(local_file_name=glb_name + ".glb", oss_file_dirname=OSS_STL_PATH)
            upload_file_to_oss(local_file_name=glb_name + ".stp", oss_file_dirname=OSS_STL_PATH)
            os.remove(path=glb_name + ".glb")
            os.remove(path=glb_name + ".stp")
            out_json["Part"]["glb_path"].append(OSS_STL_PATH + "/" + glb_name + ".glb")
            out_json["Part"]["stp_path"].append(OSS_STL_PATH + "/" + glb_name + ".stp")
    except:
        code = 500
        out_json = {}
        msg = "error"
    # a = [[M_1[i][j] for j in range(4)] for i in range(3)]
    #
    #
    # T = gp_Trsf()
    # T.SetValues(a[0][0], a[0][1], a[0][2], a[0][3],
    #             a[1][0], a[1][1], a[1][2], a[1][3],
    #             a[2][0], a[2][1], a[2][2], a[2][3])
    # trans = BRepBuilderAPI_Transform(T)
    # new_connectors=[]
    # for connector in connectors:
    #     myshape = TopoDS_Shape(connector)
    #     trans.Perform(myshape)
    #     new_shape = trans.Shape()
    #     new_connectors.append(new_shape)

    # from OCC.Display.SimpleGui import init_display
    #
    # display, start_display, add_menu, add_function_to_menu = init_display("wx")
    #
    #
    # comp = CC.get_compound()
    #
    #
    #
    # display.DisplayShape(compound, update=True)
    # display.DisplayShape(connectors,update=True)
    # # display.DisplayShape(new_connectors,update=True)
    # # display.DisplayShape(new_shape,update=True)
    # start_display()

    result = {}
    result["code"] = code
    result["data"] = out_json
    result["msg"] = msg
    return result


@app.post('/part2prism')
async def part2prims(json_file: D):
    out_json = json_file
    return out_json


if __name__ == '__main__':
    import uvicorn

    uvicorn.run(app, host="0.0.0.0", port=173)
